#pragma once


#include <iostream>
#include <vector>
#include <glm/glm.hpp>
#include <glm/trigonometric.hpp>
#include "../wrapper/log/Logger.h"
#include "../wrapper/monitor/GLDebug.hpp"
#include "../global/ChineseOutput.hpp"
#include "../global/EngineDataProperties.h"
#include "../application/app/Application.h"
#include "../glFramework/shader/Shader.h"
#include "../glFramework/constant/engine_layout.h"
#include "../glFramework/texture/Texture.h"
#include "../glFramework/utils/ResourceLoadUtils.h"
#include "../glFramework/bo/VBO.h"
#include "../glFramework/bo/VAO.h"
#include "../glFramework/constant/engine_uniform.h"
#include <memory>

#include "bo/EBO.h"
#include "../global/output.hpp"
#include "../application/camera/PerspectiveCamera.h"
#include "../application/camera/control/TrackBallCameraControl.h"
#include "../glFramework/geo/Cube.h"
#include "../glFramework/geo/Triangle.h"
#include "../glFramework/geo/Sphere.h"
#include "../glFramework/geo/Plane.h"
#include "../glFramework/geo/GridPlane.h"

/**
 * 测试引擎的相机系统
 *
 */
struct MvpMatrix {
    glm::mat4 model = glm::mat4(1.0f);
    glm::mat4 view = glm::mat4(1.0f);
    glm::mat4 proj = glm::mat4(1.0f);
};

inline const char* vertexPath = "../demo/shader/phong_light_scene/color_alternate_grid_vertex.glsl";
inline const char* fragmentPath = "../demo/shader/phong_light_scene/color_alternate_grid_fragment.glsl";
inline MvpMatrix mvpMatrix;

inline TrackBallCameraControl mController;
inline PerspectiveCamera mCamera;

inline void onResize(int w, int h) {
    glViewport(0, 0, w, h);
}

inline void onKeyBoard(int key, int action, int mods) {
    if (key == GLFW_KEY_ESCAPE) {
        glfwSetWindowShouldClose(EngineApp.getCurrentWindow(), true);
    }

    mController.onKeyBoard(key, action, mods);
}

inline void onCursor(double xpos, double ypos) {
    mController.onCursor(xpos, ypos);
}

inline void onMouse(int button, int action, int mods) {
    double x, y;
    EngineApp.getCurrentCursorPos(&x, &y);
    mController.onMouse(button, action, x, y);
}

inline void render() {
    ChineseOutput::init();
    EngineApp.initDefaultWindowConfig();
    EngineApp.setResizeCallback(onResize);
    EngineApp.setKeyBoardCallback(onKeyBoard);
    EngineApp.setCursorCallback(onCursor);
    EngineApp.setMouseCallback(onMouse);
    EngineApp.init();

    PerspectiveParams param;
    param.fov = 45.f;
    param.aspect = EngineApp.getWindowAspectRatio();
    param.zNear = 0.1f;
    param.zFar = 7000.f;
    mCamera.setPerspectiveParams(param);
    mCamera.setCameraParams(glm::vec3(0.f, 3.f, 3.f), glm::vec3(0.f, 1.f, 0.f), glm::vec3(1.f, 0.f, 0.f));
    mController.setCamera(&mCamera);
    mController.setEnableControlInfo(true);
    mController.setTrackBallRadius(3.f);
    mController.setMouseSensitivity(0.0005f);
    mController.setEnableEulerAnglePitch(false);

    GridPlane gridPlane = GridPlane(6000.f, 6000.f, 10.f,
        glm::vec3(0.f, 1, 0.f), glm::vec3(0.f, -2.5f, -30.f), glm::vec3(0.75),
        glm::vec3(0.45), GridGenType::MOD);
    gridPlane.setShader(vertexPath, fragmentPath);
    gridPlane.setGridAmbient(0.77f);

    mvpMatrix.view = glm::lookAt(glm::vec3(0.f, 0.f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    mvpMatrix.proj = glm::perspective(glm::radians(45.f), EngineApp.getWindowAspectRatio(), 0.f, 100.f);

    while (EngineApp.update()) {
        glClear(GL_COLOR_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

        mController.update();

        gridPlane.draw(mvpMatrix.model, mCamera.getViewMatrix(), mCamera.getProjectMatrix());
    }

    gridPlane.destroy();
    EngineApp.destroy();
}